package com.biao.juc;

import java.util.concurrent.*;

public class Demo02_ThreadPoolExecutor {

    // ThreadPoolExecutor 参数说明
    /*
    public ThreadPoolExecutor(int corePoolSize,     // 核心线程数, 核心线程一直保持运行
                              int maximumPoolSize,  // 最大线程数: 大于核心线程,并且不超过任务队列时候, 额外创建的线程，但不会超过最大线程,一般不会和核心线程数设置一样
                              long keepAliveTime,   // 除了核心线程，额外另外创建线程的存活时间,超过存在时间就会销毁
                              TimeUnit unit,        // keepAliveTime (额外超出核心线程的线程)的时间单位
                              BlockingQueue<Runnable> workQueue,    // 任务队列，保存待执行的任务
                              ThreadFactory threadFactory,      // 线程工厂，一般不用
                              RejectedExecutionHandler handler) {       // 拒绝策略　　
        if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

    // 最大可执行任务数是: 最大线程数 + 任务队列的数量, 超过这个线程数就会走拒绝策略
    // AbortPolicy 丢弃任务,抛个运行时异常
    // CallerRunsPolicy 执行任务
    // DiscardPolicy 忽视,什么都不发生
    // DiscardOldestPolicy 从队列提出最先进入队列的任务, 也就是最后执行的那个任务
    // 实现 RejectedExecutionHandler 接口, 自定义处理器

     */
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService executor = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()    // 拒绝策略，有好几种，具体用哪种看业务场景
        );

        try {
            for (int i = 0; i < 10; i++) {
                executor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 用完后需要关闭线程池的连接
            executor.shutdown();
        }
    }
}
